package cn.xttc.edu.util;

import cn.xttc.edu.entity.DataGridResult;
import cn.xttc.edu.entity.ExpenseRule;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 我的工具类
 *
 * @author yl
 */
public class MyUtil {
    private MyUtil(){}

    /**
     * 生成订单号 年月日时分秒+4位随机数
     *
     * @return 订单号字符串
     */
    public static String getOrderId() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        return sdf.format(new Date()) + String.format("%04d", new Random().nextInt(9999));
    }

    /**
     * 生成时间的字符串
     *
     * @param time time
     * @return 时间字符串
     */
    public static String getTimeStr(LocalDateTime time) {
        DecimalFormat df = new DecimalFormat("00");
        String month = df.format(time.getMonthValue());
        String day = df.format(time.getDayOfMonth());
        String hour = df.format(time.getHour());
        return month + "月" + day + "日 " + hour + ":00:00";
    }

    /**
     * 计算订单价格
     * @param rule 费用规则
     * @param distance 订单距离
     * @return 订单价格
     */
    public static BigDecimal getOrderPrice(ExpenseRule rule, double distance) {
        BigDecimal price;
        if (distance <= 5) {
            price = rule.getStartPrice();
        } else if (distance <= 25) {
            price = rule.getStartPrice()
                    .add(BigDecimal.valueOf(distance-5).multiply(rule.getPriceBetween5And25()));
        } else if (distance <= 60) {
            price = rule.getStartPrice()
                    .add(BigDecimal.valueOf(20).multiply(rule.getPriceBetween5And25()))
                    .add(BigDecimal.valueOf(distance-25).multiply(rule.getPriceBetween25And60()));
        } else {
            price = rule.getStartPrice()
                    .add(BigDecimal.valueOf(20).multiply(rule.getPriceBetween5And25()))
                    .add(BigDecimal.valueOf(35).multiply(rule.getPriceBetween25And60()))
                    .add(BigDecimal.valueOf(distance-60).multiply(rule.getPriceGt60()));
        }
        return price;
    }

    /**
     * 根据UUID生成文件名
     * @return 件名
     */
    public static String getUUIDFileName() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replace("-", "");
    }

    /**
     * 根据给定的文件名和后缀截取文件名
     * @param fileName 文件名
     * @return 文件类型
     */
    public static String getFileType(String fileName){
        int index = fileName.lastIndexOf(".");
        return fileName.substring(index);
    }

    /**
     * 将page对象专为bootstrap table能识别的json字符串
     * @param page page对象
     * @return json字符串
     */
    public static String formatReturnData(IPage page) {
        return JSON.toJSONString(new DataGridResult(page.getTotal(), page.getRecords()));
    }

    /**
     * 1.MD5（message-digest algorithm 5）信息摘要算法，
     *   它的长度一般是32位的16进制数字符串（如81dc9bdb52d04dc20036dbd8313ed055）
     * 2.由于系统密码明文存储容易被黑客盗取
     * 3.应用：注册时，将密码进行md5加密，存到数据库中，防止可以看到数据库数据的人恶意篡改。
     *       登录时,将密码进行md5加密,与存储在数据库中加密过的密码进行比对
     * 4.md5不可逆，即没有对应的算法，从产生的md5值逆向得到原始数据。
     *   但是可以使用暴力破解，这里的破解并非把摘要还原成原始数据，如暴力枚举法。
     *
     */
    public static String getMD5(String str){
        try {
            //创建具有指定算法名称的摘要
            MessageDigest md = MessageDigest.getInstance("SHA");
            //使用指定的字节数组更新摘要
            md.update(str.getBytes());
            //进行哈希计算并返回一个字节数组
            byte[] mdBytes = md.digest();
            StringBuilder hash = new StringBuilder();
            //循环字节数组
            for (byte mdByte : mdBytes) {
                int temp;
                //如果有小于0的字节,则转换为正数
                if (mdByte < 0) {
                    temp = 256 + mdByte;
                } else {
                    temp = mdByte;
                }
                if (temp < 16) {
                    hash.append("0");
                }
                //将字节转换为16进制后，转换为字符串
                hash.append(Integer.toString(temp, 16));
            }
            return hash.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取当前日期一周的日期
     * @return 日期字符串集合
     */
    public static List<String> getWeeklyDate() {
        ArrayList<String> dateList = new ArrayList<>();

        //设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cld = Calendar.getInstance(Locale.CHINA);
        //以周一为首日
        cld.setFirstDayOfWeek(Calendar.MONDAY);
        //当前时间
        cld.setTimeInMillis(System.currentTimeMillis());

        //周一
        cld.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        String mondayStr = df.format(cld.getTime()) + " 00:00:00";
        dateList.add(mondayStr);

        for (int i = 1; i <= 7; i++) {
            cld.add(Calendar.DATE, 1);
            String dateStr = df.format(cld.getTime()) + " 00:00:00";
            dateList.add(dateStr);
        }

        return dateList;
    }
}
